package com.panopset.game.blackjack;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Strategy {

    public enum StratCat {
        NONE, SOFT, SPLIT, HARD
    }

    private final BlackjackConfig c;

    public Strategy(BlackjackConfig config) {
        c = config;
        DFT_SL = new StrategyLine(0, "", c);
    }

    public RecommendedAction getRecommendedAction(final Situation s) {
        return findStrategyLine(s).getAction(s);
    }

    private List<String> stratLines;

    private List<String> getStratLines() {
        if (stratLines == null) {
            stratLines = c.getStrategyData();
        }
        return stratLines;
    }

    private final StrategyLine DFT_SL;
    private Map<StratCat, Map<String, StrategyLine>> sls;
    private String hardHeader = "";
    private String softHeader = "";
    private String splitHeader = "";

    public String getHeaderFor(StratCat cat) {
        getStrategyLines();
        switch (cat) {
        case SOFT:
            return softHeader;
        case HARD:
            return hardHeader;
        case SPLIT:
            return splitHeader;
        }
        return "";
    }

    public Map<StratCat, Map<String, StrategyLine>> getStrategyLines() {
        StratCat reading = StratCat.NONE;
        if (sls == null) {
            sls = new HashMap<StratCat, Map<String, StrategyLine>>();
            sls.put(StratCat.HARD, new HashMap<String, StrategyLine>());
            sls.put(StratCat.SOFT, new HashMap<String, StrategyLine>());
            sls.put(StratCat.SPLIT, new HashMap<String, StrategyLine>());
            int i = 0;
            for (String s : getStratLines()) {
                if (s.length() < 1 || s.substring(0, 1).equals("#")) {
                    continue;
                }
                if (StratCat.HARD.toString()
                        .equalsIgnoreCase(s.substring(0, 4))) {
                    reading = StratCat.HARD;
                    i = 0;
                    hardHeader = s;
                } else if (StratCat.SOFT.toString().equalsIgnoreCase(
                        s.substring(0, 4))) {
                    reading = StratCat.SOFT;
                    i = 0;
                    softHeader = s;
                } else if (StratCat.SPLIT.toString().equalsIgnoreCase(
                        s.substring(0, 5))) {
                    reading = StratCat.SPLIT;
                    i = 0;
                    splitHeader = s;
                } else {
                    StrategyLine sl = new StrategyLine(++i, s, c);
                    if (StratCat.HARD.equals(reading)) {
                        sls.get(StratCat.HARD).put(sl.getKey(), sl);
                    } else if (StratCat.SOFT.equals(reading)) {
                        sls.get(StratCat.SOFT).put(sl.getKey(), sl);
                    } else if (StratCat.SPLIT.equals(reading)) {
                        sls.get(StratCat.SPLIT).put(sl.getKey(), sl);
                    }
                }
            }
        }
        return sls;
    }

    public StrategyLine findStrategyLine(final Situation s) {
        StrategyLine l = null;
        String key = "";
        if (s == null) {
            return null;
        }
        if (s.d == null) {
            return null;
        }
        if (s.getHand().isSplitable(c)) {
            int cv = s.getHand().getHardValueOf(0);
            key = "" + cv + "," + cv;
            if (key.equals("1,1")) {
                key = "A,A";
            }
            l = getStrategyLines().get(StratCat.SPLIT).get(key);
            if (l != null) {
                return l;
            }
        }
        int v = s.getHand().getValue();
        if (s.getHand().isSoft()) {
            if (v > 19) {
                key = "20+";
            } else {
                key = "" + v;
            }
            l = getStrategyLines().get(StratCat.SOFT).get(key);
            if (l != null) {
                return l;
            }
        } else {
            if (v > 17) {
                key = "18+";
            } else if (v < 8) {
                key = "7";
            } else {
                key = "" + v;
            }
            l = getStrategyLines().get(StratCat.HARD).get(key);
            if (l != null) {
                return l;
            }
        }
        return DFT_SL;
    }

    public RecommendedAction getRecommendation(final Situation s) {
        StrategyLine sl = findStrategyLine(s);
        if (sl == null) {
            return new RecommendedAction("", "");
        } else {
            return sl.getAction(s);
        }
    }
}
